<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tree paint</title>
</head>
<body>
    <style>
        canvas {
            width: 512px;
            height: 512px;
        }
    </style>
    <canvas width="512" height="512"></canvas>
    <script>
        class Vector2D extends Array {
            constructor(x = 1, y = 0) {
                super(x, y);
            }

            set x(v) {
                this[0] = v;
            }

            set y(v) {
                this[1] = v;
            }

            get x() {
                return this[0];
            }

            get y() {
                return this[1];
            }

            get length() {
                return Math.hypot(this.x, this.y);
            }

            get dir() {
                return Math.atan2(this.y, this.x);
            }

            copy() {
                return new Vector2D(this.x, this.y);
            }

            add(v) {
                this.x += v.x;
                this.y += v.y;
                return this;
            }

            sub(v) {
                this.x -= v.x;
                this.y -= v.y;
                return this;
            }

            scale(a) {
                this.x *= a;
                this.y *= a;
                return this;
            }

            cross(v) {
                return this.x * v.y - v.x * this.y;
            }

            dot(v) {
                return this.x * v.x + v.y * this.y;
            }

            normalize() {
                return this.scale(1 / this.length);
            }

            rotate(rad) {
                const c = Math.cos(rad),
                s = Math.sin(rad);
                const [x, y] = this;

                this.x = x * c + y * -s;
                this.y = x * s + y * c;

                return this;
            }
        }

        const canvas = document.querySelector('canvas')
        const context = canvas.getContext('2d')

        context.translate(0, canvas.height)
        context.scale(1, -1)
        context.lineCap = 'round'

        function drawBranch(context, v0, length, thickness, dir, bias) {
            const v = new Vector2D().rotate(dir).scale(length);
            const v1 = v0.copy().add(v);

            context.lineWidth = thickness;
            context.beginPath();
            context.moveTo(...v0);
            context.lineTo(...v1);
            context.stroke();

            if(thickness > 2) {
                const left = Math.PI / 4 + 0.5 * (dir + 0.2) + bias * (Math.random() - 0.5);
                drawBranch(context, v1, length * 0.9, thickness * 0.8, left, bias * 0.9);
                const right = Math.PI / 4 + 0.5 * (dir - 0.2) + bias * (Math.random() - 0.5);
                drawBranch(context, v1, length * 0.9, thickness * 0.8, right, bias * 0.9);
            }

            if(thickness < 5 && Math.random() < 0.3) {
                context.save();
                context.strokeStyle = '#c72c35';
                const th = Math.random() * 6 + 3;
                context.lineWidth = th;
                context.beginPath();
                context.moveTo(...v1);
                context.lineTo(v1.x, v1.y - 2);
                context.stroke();
                context.restore();
            }
        }

        const v0 = new Vector2D(256, 0)
        drawBranch(context, v0, 50, 10, 1, 3)

    </script>
</body>
</html>